﻿#include "CELLBuffer.h"
#include "CELL.h"
#include <string.h>


CELLBuffer::CELLBuffer(int nSize) 
	: _nSize(nSize)
{
	_pBuff = new char[_nSize];
}

CELLBuffer::~CELLBuffer()
{
	if (_pBuff)
	{
		delete[] _pBuff;
		_pBuff = nullptr;
	}
}

int CELLBuffer::write2socket(SOCKET sockfd)
{
	int ret = 0;
	// 本客户端消息发送缓冲区中有数据并且本客户端套接字是有效的
	if (_nLast > 0 && INVALID_SOCKET != sockfd)
	{
		// 发送发送缓冲区的数据
		ret = send(sockfd, _pBuff, _nLast, 0);
		if (ret <= 0)
		{
			return SOCKET_ERROR;
		}
		else if (ret == _nLast)
		{
			// 将发送缓冲区的尾部指针置0
			_nLast = 0;
		}
		else
		{
			_nLast -= ret;
			memcpy(_pBuff, _pBuff + ret, _nLast);
		}
		
		// 
		_fullCount = 0;
	}
	// 返回0或者返回send函数的返回值
	return ret;
}

int CELLBuffer::read4socket(SOCKET sockfd)
{
	if (_nSize - _nLast > 0)
	{
		// 还有空位置可以用
		// 接受客户端数据
		char* szRecv = _pBuff + _nLast;
		int nLen = (int)recv(sockfd, szRecv, _nSize - _nLast, 0);
		if (nLen <= 0)
		{
			CELLLog_Debug("CELLBuffer::read4socket, nLen = %d", nLen);
			return SOCKET_ERROR;
		}
		// 缓冲区尾部位置后移
		_nLast += nLen;
		return nLen;
	}
	return 0;
}

bool CELLBuffer::push(const char* pData, int nLen)
{
	/*
		在这里添加数据的时候如果超过了，可以在这里扩展原空间
			或者写入数据库或磁盘，看需求
	*/
	if (_nLast + nLen <= _nSize)
	{
		// 将要发送的数据拷贝到发送缓冲区尾部
		memcpy(_pBuff + _nLast, pData, nLen);
		// 更新缓冲区长度
		_nLast += nLen;
		if (_nLast == SEND_BUF_SIZE)
		{
			// 发送缓冲区刚好满
			++_fullCount;
		}
		return true;
	}
	else
	{
		// 发送缓冲区已满(超出)
		++_fullCount;
	}

	return false;
}

void CELLBuffer::pop(int nLen)
{
	int n = _nLast - nLen;
	// 判断删除的数据长度是正常的
	if (n > 0)
	{
		memcpy(_pBuff, _pBuff + nLen, n);
	}
	// 缓冲区尾部指针前移
	_nLast = n;
	if (_fullCount > 0)
		--_fullCount;
}

bool CELLBuffer::hasMsg()
{
	if (_nLast >= sizeof(DataHeader))
	{
		// 强转类型就可以知道这次消息的长度了
		DataHeader* header = (DataHeader*)_pBuff;
		// 判断客户端消息缓冲区的数据长度是否大于消息长度
		return _nLast >= header->dataLength;
	}
	// 缓冲区数据不够一条消息长度
	return false;
}

bool CELLBuffer::needWrite()
{
	// 当客户端应用时要判断是否要发送数据给服务端，只要缓冲区有数据就可以了
	return _nLast > 0;
}

char* CELLBuffer::data()
{
	return _pBuff;
}

int CELLBuffer::buffSize()
{
	return _nSize;
}

int CELLBuffer::dataLen()
{
	return _nLast;
}
